[アップデート]AWS SAM CLIでAWS環境上のLambda関数のテストイベントを操作できるようになりました
初めに
本日AWS SAM CLI v1.98.0がリリースされました。
今回のアップデートではsam remote
コマンドに新たなサブコマンドtest-event
が追加されSAM経由でAWS環境上のLambda関数のテストイベントを操作できるようになります。
また合わせてsam remote invoke
コマンドに新たなオプション--test-event-name
が追加されAWS環境上に設置されているイベントデータを使えるようになっております。
remote invoke
コマンドについては今年の6月ごろのアップデート追加されたサブコマンドでSAMを通してローカルではなく実際のAWS環境上のLambda関数を実行できる機能となります。
以前はsam remote invoke
は実際にデプロイされたAWS環境上の関数を呼び出すことができたのですがテストイベントは取り扱うことができず、イベントデータに依存する関数の場合はローカルにそのデータを準備して実行する必要がありました。
そのため運用等の兼ね合いでマネージメントコンソール上で作成されたイベントが欲しい場合や、複数人で共有したい場合はSAM外の別の手段を用意する必要がありこの点がネックとなっておりました。
今回のアップデートによってローカル・リモート間でのテストデータのやり取りがSAM上で完結できるようになりよりスムーズに開発検証が行えるようになります。
なお普段AWS側に上がらないことの多いSAMのアップデートですが珍しく本機能はWhat's newにも取り上げられております。
追加されたコマンド
4種類のサブコマンドが追加されています。
sam remote test-event list
- AWS環境上のテストイベントの一覧を取得
sam remote test-event put
- ローカルからAWS環境上にテストイベントをアップロード
sam remote test-event get
- AWS環境上の特定のテストイベントを取得
sam remote test-event delete
- AWS環境上の特定のテストイベントを削除する
またsam remote invoke
に対して追加されたオプションとしては--test-event-name
となり、こちらにAWS環境上に保存されているイベント名を指定することでそのイベントを利用しての実行が可能です。
試してみる
サンプルのHello Wolrdの関数をデプロイして実行してみます。
SAMには既存コマンドでローカル上でテストイベントデータを作成するsam local generate-event
があるのでこちらでイベントを作成してアップロードします。
# デプロイ直後は何もイベントがない。空の結果が返却されるのではなくエラーとなるらしい % sam remote test-event list Error: lambda-testevent-schemas registry not found. There are no saved events. # アップロードのためにローカル上でAPI Gateway経由のアクセスのイベントをファイルに保存する(既存コマンド) % sam local generate-event apigateway aws-proxy > api-event.json # 先ほどのファイルを指定してアップロードする % sam remote test-event put --name simple-api-event --file events/api-event.json Put remote event 'simple-api-event' completed successfully # AWS環境上に先ほどのイベントが上がっていることが確認できる # listは名前のみの一覧 % sam remote test-event list simple-api-event # getでは具体的なイベントの中身が見られるので保存が必要ならリダイレクトでよしなにする。 % sam remote test-event get --name simple-api-event {"body": "eyJ0ZXN0IjoiYm9keSJ9", "resource": "/{proxy+}", "path": "/path/to/resource", "httpMethod": "POST", "isBase64Encoded": true, "queryStringParameters": {"foo": "bar"}, "multiValueQueryStringParameters": {"foo": ["bar"]}, "pathParameters": {"proxy": "/path/to/resource"}, "stageVariables": {"baz": "qux"}, "headers": {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Encoding": "gzip, deflate, sdch", "Accept-Language": "en-US,en;q=0.8", "Cache-Control": "max-age=0", "CloudFront-Forwarded-Proto": "https", "CloudFront-Is-Desktop-Viewer": "true", "CloudFront-Is-Mobile-Viewer": "false", "CloudFront-Is-SmartTV-Viewer": "false", "CloudFront-Is-Tablet-Viewer": "false", "CloudFront-Viewer-Country": "US", "Host": "1234567890.execute-api.us-east-1.amazonaws.com", "Upgrade-Insecure-Requests": "1", "User-Agent": "Custom User Agent String", "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", "X-Forwarded-For": "127.0.0.1, 127.0.0.2", "X-Forwarded-Port": "443", "X-Forwarded-Proto": "https"}, "multiValueHeaders": {"Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"], "Accept-Encoding": ["gzip, deflate, sdch"], "Accept-Language": ["en-US,en;q=0.8"], "Cache-Control": ["max-age=0"], "CloudFront-Forwarded-Proto": ["https"], "CloudFront-Is-Desktop-Viewer": ["true"], "CloudFront-Is-Mobile-Viewer": ["false"], "CloudFront-Is-SmartTV-Viewer": ["false"], "CloudFront-Is-Tablet-Viewer": ["false"], "CloudFront-Viewer-Country": ["US"], "Host": ["0123456789.execute-api.us-east-1.amazonaws.com"], "Upgrade-Insecure-Requests": ["1"], "User-Agent": ["Custom User Agent String"], "Via": ["1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)"], "X-Amz-Cf-Id": ["cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA=="], "X-Forwarded-For": ["127.0.0.1, 127.0.0.2"], "X-Forwarded-Port": ["443"], "X-Forwarded-Proto": ["https"]}, "requestContext": {"accountId": "123456789012", "resourceId": "123456", "stage": "prod", "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", "requestTime": "09/Apr/2015:12:34:56 +0000", "requestTimeEpoch": 1428582896000, "identity": {"cognitoIdentityPoolId": null, "accountId": null, "cognitoIdentityId": null, "caller": null, "accessKey": null, "sourceIp": "127.0.0.1", "cognitoAuthenticationType": null, "cognitoAuthenticationProvider": null, "userArn": null, "userAgent": "Custom User Agent String", "user": null}, "path": "/prod/path/to/resource", "resourcePath": "/{proxy+}", "httpMethod": "POST", "apiId": "1234567890", "protocol": "HTTP/1.1"}}
AWS環境上を確認すると作成したイベントがアップロードされていることが確認できます。
少し不便な点としてはputの際は上記のように改行やインデントを保持したままアップロードされているようですが、getで取得されたデータには改行やインデントがなくなってしまっているのでデータ次第で手で触るなら一度整形しないといけない点です(大元のAPIの仕様のせいな気がする)。
せっかくなのでremote invoke
経由でアップロードしたイベントを使った実行を試してみます。
返却するmessage値を"Hello World"固定のメッセージではなくevent
を返すようにしています。
# 特に指定しないとイベントがないのでmessageの値は空 $ sam remote invoke Invoking Lambda Function HelloWorldFunction START RequestId: e6fb9028-7ca3-43f2-8ec6-98266989c795 Version: $LATEST END RequestId: e6fb9028-7ca3-43f2-8ec6-98266989c795 REPORT RequestId: e6fb9028-7ca3-43f2-8ec6-98266989c795 Duration: 1.40 ms Billed Duration: 2 ms Memory Size: 128 MB Max Memory Used: 36 MB Init Duration: 120.34 ms {"statusCode": 200, "body": "{\"message\": {}}"}% # 先ほど指定したイベント名を指定するとその内容が出力されていることが確認できる。 $ sam remote invoke --test-event-name simple-api-event Invoking Lambda Function HelloWorldFunction START RequestId: 4fc102a5-7139-4527-9871-b3a616a44191 Version: $LATEST END RequestId: 4fc102a5-7139-4527-9871-b3a616a44191 REPORT RequestId: 4fc102a5-7139-4527-9871-b3a616a44191 Duration: 19.65 ms Billed Duration: 20 ms Memory Size: 128 MB Max Memory Used: 37 MB {"statusCode": 200, "body": "{\"message\": {\"body\": \"eyJ0ZXN0IjoiYm9keSJ9\", \"resource\": \"/{proxy+}\", \"path\": \"/path/to/resource\", \"httpMethod\": \"POST\", \"isBase64Encoded\": true, \"queryStringParameters\": {\"foo\": \"bar\"}, \"multiValueQueryStringParameters\": {\"foo\": [\"bar\"]}, \"pathParameters\": {\"proxy\": \"/path/to/resource\"}, \"stageVariables\": {\"baz\": \"qux\"}, \"headers\": {\"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\", \"Accept-Encoding\": \"gzip, deflate, sdch\", \"Accept-Language\": \"en-US,en;q=0.8\", \"Cache-Control\": \"max-age=0\", \"CloudFront-Forwarded-Proto\": \"https\", \"CloudFront-Is-Desktop-Viewer\": \"true\", \"CloudFront-Is-Mobile-Viewer\": \"false\", \"CloudFront-Is-SmartTV-Viewer\": \"false\", \"CloudFront-Is-Tablet-Viewer\": \"false\", \"CloudFront-Viewer-Country\": \"US\", \"Host\": \"1234567890.execute-api.us-east-1.amazonaws.com\", \"Upgrade-Insecure-Requests\": \"1\", \"User-Agent\": \"Custom User Agent String\", \"Via\": \"1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)\", \"X-Amz-Cf-Id\": \"cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==\", \"X-Forwarded-For\": \"127.0.0.1, 127.0.0.2\", \"X-Forwarded-Port\": \"443\", \"X-Forwarded-Proto\": \"https\"}, \"multiValueHeaders\": {\"Accept\": [\"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\"], \"Accept-Encoding\": [\"gzip, deflate, sdch\"], \"Accept-Language\": [\"en-US,en;q=0.8\"], \"Cache-Control\": [\"max-age=0\"], \"CloudFront-Forwarded-Proto\": [\"https\"], \"CloudFront-Is-Desktop-Viewer\": [\"true\"], \"CloudFront-Is-Mobile-Viewer\": [\"false\"], \"CloudFront-Is-SmartTV-Viewer\": [\"false\"], \"CloudFront-Is-Tablet-Viewer\": [\"false\"], \"CloudFront-Viewer-Country\": [\"US\"], \"Host\": [\"0123456789.execute-api.us-east-1.amazonaws.com\"], \"Upgrade-Insecure-Requests\": [\"1\"], \"User-Agent\": [\"Custom User Agent String\"], \"Via\": [\"1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)\"], \"X-Amz-Cf-Id\": [\"cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==\"], \"X-Forwarded-For\": [\"127.0.0.1, 127.0.0.2\"], \"X-Forwarded-Port\": [\"443\"], \"X-Forwarded-Proto\": [\"https\"]}, \"requestContext\": {\"accountId\": \"123456789012\", \"resourceId\": \"123456\", \"stage\": \"prod\", \"requestId\": \"c6af9ac6-7b61-11e6-9a41-93e8deadbeef\", \"requestTime\": \"09/Apr/2015:12:34:56 +0000\", \"requestTimeEpoch\": 1428582896000, \"identity\": {\"cognitoIdentityPoolId\": null, \"accountId\": null, \"cognitoIdentityId\": null, \"caller\": null, \"accessKey\": null, \"sourceIp\": \"127.0.0.1\", \"cognitoAuthenticationType\": null, \"cognitoAuthenticationProvider\": null, \"userArn\": null, \"userAgent\": \"Custom User Agent String\", \"user\": null}, \"path\": \"/prod/path/to/resource\", \"resourcePath\": \"/{proxy+}\", \"httpMethod\": \"POST\", \"apiId\": \"1234567890\", \"protocol\": \"HTTP/1.1\"}}}"}%
最後に設置したテストイベントを消しておきます。
% sam remote test-event delete --name simple-api-event Delete remote event 'simple-api-event' completed successfully % sam remote test-event list Error: No events found for function HelloWorldFunction
なお今回は単一の関数のみが存在するテンプレートだったので特別指定は行っていなかったのですが、複数関数があるような環境では実行対象の関数名を指定して実行する必要があります。
% sam remote test-event list HelloWorldFunction simple-api-event
終わりに
今回のアップデートは複数人開発を行っている場合では非常に嬉しい機能ではないでしょうか。
remote invoke
を利用している場合はより便利にできますが、特に利用していなくとも開発メンバー間、運用・開発間のメンバーのデータ受け渡し等様々な場面でサクッとデータのやり取りができます(実際の環境に上がるのでそれがいいかはどうかは別として)。
これでチャットツール側の不要な整形やコピペミス等に怯える必要もありません。